An analysis of Krugman's theory, using Pflüger's Model

Group members ANR
Arne Bor 938230
Job Teurlinx 943070
Indira van Asperen 261841

Introduction

Spatial economics are becoming a more and more important part of economics. Seminal contributions by Krugman (1991) have proven their value. Economists need to start thinking in terms of agglomeration, core and periphery to answer questions about regional competition (Pflüger, 2004). Geographical economics used to be a small part of economics, despite its explanatory power (Krugman, 1991). Krugman argues that forces of agglomeration can be explained by economic geography, using models borrowed from industrial organization. He uses them to answer the question why all economic activity takes place in one core-area, leaving vast amounts of peripherical land unused.

Research Question

In this paper, we want to do the following things. First, we want to put the model set up by Pflüger, set up in 2004 (Pflüger 2004) to check the theory set up by Krugman. We will pay special attention to the ‘threshold-effect’ described by Krugman and expand the model offered by Pflüger. We want to check this model by studying the threshold effects as described by Krugman. Furthermore, we want to add several aspects: we want to model both cluster benefits and costs of agglomeration.

Theoretical Foundation

A number of reasons are offered by Krugman to explain agglomeration effects. First, agglomeration leads to a pooled labour-market where chances of finding both employers and employees are larger for both labourers as firms than in non-agglomerized regions. Second, and more importantly, it’s possible that firms in a cluster are more efficient than their isolated counterparts in the periphery, due to information spill-over effects. Krugman argues that it therefore makes sense that agglomeration takes place. He and Pflüger describe a two-sector world, where the agricultural sector uses land and the manufacture sectors uses land only modestly, and consumers spend a sufficient large fraction of their wealth on manufacturing goods. Manufactured goods are produced by skilled labourers, while agricultural goods are produced by unskilled labourers. There are transport costs for manufactured but not for agricultural goods. In this world, Krugman argues that a circular effect takes place: manufactural production is located where a big market is, but the market is large if the manufacturing sector is located there. He believes there is a threshold of transport costs, wealth spent on manufactured and economies of scale that must be crossed before agglomeration starts. Skilled labour is mobile, while unskilled labour is not. In the long run, human capital owners will go to regions where their utility is the highest, such that V – V = 0, where V denotes a person’s utility and V optimal utility. In the long term, where skilled labour is mobile, there is no reason why a person should choose to live somewhere where V is lower than V*.

Model

The model as described by Pflüger has the following charachteristics:
In formula form, the model has the following parameters and equations:

Table 1: Parameters

Symbol Definition
$U$ Utility
$C_\alpha$ Consumption of agricultural goods
$C_x$ Consumption of manufactured goods
$R$ Wage
$p$ Price
$\alpha$ Preference for manufactured goods
$\sigma$ Elasticity of substitution between manufacturing varieties
$\lambda$ $N \over {N+N*}$: Share of total labour supply that works in home region
$L$ Unskilled labour force
$K$ Skilled labour force
$L + K$ Total Population
$\rho$ $L\over K$: Ratio unskilled labour in home region to total skilled labour in world
$\rho*$ $L*\over K$: Ratio unskilled labour in foreign region to total skilled labour in world
$N, N^*$ varieties produced at home and abroad
$\tau$ Transport Costs
$\phi$ $\tau^{1-\sigma}$

Model Equations

Therefore:
$$U = C_\alpha + \alpha ln(C_x)$$
$$C_x = (\int\limits_0^\eta x_i^{{\sigma-1}\over{\sigma}}+\int\limits_0^\eta x_j^{{\sigma-1}\over{\sigma}})^{{\sigma-1}\over{\sigma}}$$
There is a budget constraint: $$PC_x + C_a = Y$$
Maximisation leads to:
$$P = [NP_i^{1-\sigma} + N^*(\tau P_j)^{1-\sigma}]^{{1}\over{1-\sigma}}$$
$$C_x = \alpha P^{-1}$$
$$C_\alpha = Y - \alpha$$
$$x_i = \alpha P_i^{-\sigma}P^{\sigma - 1}$$
$$x_j = \alpha (\tau P_j)^{-\sigma}P^{\sigma-1}$$
$$V = -\alpha ln(P)+Y - \alpha ln(x-1)$$
Production is determined by:
$$X(L+K)X_i + (L+K)\tau x_j$$
Technology is such that $L_i=cX_i$, with the marginal cost given by c.
Prices are constant markups:
$$P_i = P_j = {{c\sigma} \over{(\sigma - 1)}}$$
In the short run, skilled labour is immobile. $$N = K$$ and $$N^* = K^*$$.
Then:
$$\sigma R - {{\alpha (L+K)} \over{K+\phi K}} + {{\phi\alpha(L+K) \over {\phi K + K}}}$$ and $$\sigma R - {{\phi\alpha(L+K) \over {K+\phi K}}} + {{\alpha(L+K) \over {\phi K + K}}}$$
And in the long run, there exists a difference between optimal indirect utility $$V^*$$ and indirect utility V:

$$V-V^* = {{\alpha} \over {1-\sigma}}ln[{{\lambda\phi+(1-\lambda)} \over {\lambda+(1-\lambda)\phi}}]+{{\alpha(1-\phi)} \over {\sigma}}[{{\rho+\lambda} \over {\lambda+(1-\lambda)\phi}} - {{\rho*+(1-\lambda)} \over {\lambda\phi+(1-\lambda)}}]$$

Pflügers Model

In the following figure we present Pflügers model, as described in his paper. The values of the parameters will be presented below, in which $\lambda$ is the varying factor in the utility function.

Parameters Model Pflüger

Symbol Value
$\alpha$ 0.3
$\sigma$ 6
$\tau$ 1.1; 1.4; 1.5
$\lambda$ Ranging from 0.1 (intervals of 0.1
$\rho$ 1
$\rho*$ 1

Parameters $\tau$ and $\phi$

$\tau$ $\phi$
1.1 0.621
1.4 0.186
1.5 0.132

Execution

In [134]:
import math
import numpy as np
import pandas as pd
from scipy import arange, optimize
import matplotlib.pyplot as plt
%matplotlib inline

Exogenous parameters

In [149]:
# Defining exogenous parameters

alpha = 0.3      # preference for manufactured goods
sigma = 6        # elasticity of subsitituion between manufactured varieties
rho = 1          # ratio unskilled labour in home region to total skilled labour in world
tau = 0          # transport costs
phi = 0          # parameter for transport cost
lamda = arange (0.1,1.1,0.1) # Initialization lambda ranging from 0.1 to 1.0
In [150]:
# Check if array functions correctly (should print row from 0.1 to 1.0)
print lamda 
[ 0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9  1. ]
In [151]:
# Creating function to test utility function for range of Lambda
def utility_function(lamda): 
        return (alpha/1-sigma)*np.log((lamda*phi+(1-lamda))/(lamda+(1-lamda)*phi))+((alpha*(1-phi))/sigma)*((rho+lamda)/(lamda+(1-lamda)*phi)-(rho+(1-lamda))/(lamda*phi+(1-lamda)))
In [138]:
# Itializing parameters tau and phi for tax = 1.1
tau = 1.1        # transport costs
phi = 0.621      # parameter for transport cost

# Estimate V-V* using tax = 1.1
range_v_v = utility_function(lamda) 
print range_v_v
[-2.163503   -1.61412411 -1.07209852 -0.53486667  0.          0.53486667
  1.07209852  1.61412411  2.163503    2.72300263]
In [139]:
# Changing Parameter tau: 1.4
tau = 1.4        # transport costs
# Therefore phi becomes:
phi = 0.186      # parameter for transport cost

# Estimate V-V* using tax = 1.4
range_v_v_2 = utility_function(lamda) # Transportation cost 1.4
print range_v_v_2
[-6.95115449 -4.93819954 -3.18065755 -1.55998175  0.          1.55998175
  3.18065755  4.93819954  6.95115449  9.45003185]
In [140]:
# Changing Parameter tau: 1.5
tau = 1.5        # transport costs
# Therefore phi becomes:
phi = 0.132      # parameter for transport cost

# Estimating V-V* using tax = 1.5
range_v_v_3 = utility_function(lamda) # Transportation cost 1.4
print range_v_v_3
[ -8.01624974  -5.59448225  -3.56879307  -1.74174861   0.           1.74174861
   3.56879307   5.59448225   8.01624974  11.30024625]
In [141]:
plt.clf() # Constructing a graph for tax = 1.1, 1.4, 1.5
plt.plot(lamda, range_v_v,'-', color = 'b', linewidth = 2) # Constructs blue graphline for tax = 1.1
plt.plot(lamda, range_v_v_2,'-', color = 'r', linewidth = 2) # Constructs red graphline for tax = 1.4
plt.plot(lamda, range_v_v_3,'-', color = 'g', linewidth = 2) # Constructs green graphline for tax = 1.5
plt.title("Pflueger Model",fontsize = 15) # Titling of the graph
plt.xlabel("$\lambda$",fontsize = 15)      # Titling x-axis
plt.ylabel("$V-V^*$")                      # Titling y-axis
plt.annotate('$V-V^* (Tax = 1.1)$', xy=(0.95,utility_function(0.65)), xycoords='data', xytext=(-10,30), textcoords='offset points', arrowprops=dict(arrowstyle="->", linewidth=2, connectionstyle="arc3, rad=.2"),) # Constructing indication arrows tax = 1.1
plt.annotate('$V-V^* (Tax = 1.4)$', xy=(0.90,utility_function(0.85)), xycoords='data', xytext=(-70,30), textcoords='offset points', arrowprops=dict(arrowstyle="->", linewidth=2, connectionstyle="arc3, rad=.2"),) # Constructing indication arrows tax = 1.4
plt.annotate('$V-V^* (Tax = 1.5)$', xy=(0.95,utility_function(0.97)), xycoords='data', xytext=(-70,35), textcoords='offset points', arrowprops=dict(arrowstyle="->", linewidth=2, connectionstyle="arc3, rad=.2"),) # Constructing indication arrows tax = 1.5
plt.savefig('Pflueger Model')             # Saves the model in C:\Users\

EXPLANATION PFLUEGER MODEl

Introducing cost of living

Now we try to include a cost of living in our model in a more crowded area. For that end, we introduce a cost of living in crowded area $v$ in which $(v<0)$.

We construct the following function: $$V-V^* = {{\alpha} \over {1-\sigma}}ln[{{\lambda\phi+(1-\lambda)} \over {\lambda+(1-\lambda)\phi}}]+{{\alpha(1-\phi)} \over {\sigma}}[{{\rho+\lambda} \over {\lambda+(1-\lambda)\phi}} - {{\rho*+(1-\lambda)} \over {\lambda\phi+(1-\lambda)}}]+v(\lambda-0.5)$$ Such that if $\dot{\lambda}$ exceeds half, utility from living in that area will be lower, while it will become negative if less people live in that country, for instance because the air is cleaner in less crwoded areas. For this particular formula only the skilled labour population plays a role as the unskilled labour force is aassumed to be immobile.

In [142]:
# Defining extra parameter: cost of living
v = -1           # Cost of living in crowded area

# Constructing function including cost of living in crowded area effect
def utility_function_2(lamda):
        return (alpha/1-sigma)*np.log((lamda*phi+(1-lamda))/(lamda+(1-lamda)*phi))+((alpha*(1-phi))/sigma)*((rho+lamda)/(lamda+(1-lamda)*phi)-(rho+(1-lamda))/(lamda*phi+(1-lamda)))+v*(lamda-0.5)
In [143]:
# Itializing parameters tau and phi for tax = 1.1
tau = 1.1        # transport costs
phi = 0.621      # parameter for transport cost
# Estimate V-V* using tax = 1.1
my_range_v_v = utility_function_2(lamda) 

# Changing Parameter tau: 1.4
tau = 1.4        # transport costs
# Therefore phi becomes:
phi = 0.186      # parameter for transport cost
# Estimate V-V* using tax = 1.4
my_range_v_v_2 = utility_function_2(lamda) # Transportation cost 1.4

# Changing Parameter tau: 1.5
tau = 1.5        # transport costs
# Therefore phi becomes:
phi = 0.132      # parameter for transport cost
# Estimating V-V* using tax = 1.5
my_range_v_v_3 = utility_function_2(lamda) # Transportation cost 1.4

plt.clf() # Constructing a graph for tax = 1.1, 1.4, 1.5
plt.plot(lamda, my_range_v_v,'-', color = 'b', linewidth = 2)   # Constructs blue graphline for tax = 1.1
plt.plot(lamda, my_range_v_v_2,'-', color = 'r', linewidth = 2) # Constructs red graphline for tax = 1.4
plt.plot(lamda, my_range_v_v_3,'-', color = 'g', linewidth = 2) # Constructs green graphline for tax = 1.5
plt.title("Pflueger Model: cost of living in crowded area",fontsize = 15) # Titling of the graph
plt.xlabel("$\lambda$",fontsize = 15)      # Titling x-axis
plt.ylabel("$V-V^*$")                      # Titling y-axis
plt.annotate('$V-V^* (tax = 1.1)$', xy=(0.95,utility_function_2(0.65)), xycoords='data', xytext=(-10,30), textcoords='offset points', arrowprops=dict(arrowstyle="->", linewidth=2, connectionstyle="arc3, rad=.2"),) # Constructing indication arrows tax = 1.1
plt.annotate('$V-V^* (tax = 1.4)$', xy=(0.90,utility_function_2(0.85)), xycoords='data', xytext=(-70,30), textcoords='offset points', arrowprops=dict(arrowstyle="->", linewidth=2, connectionstyle="arc3, rad=.2"),) # Constructing indication arrows tax = 1.4
plt.annotate('$V-V^* (tax = 1.5)$', xy=(0.95,utility_function_2(0.97)), xycoords='data', xytext=(-70,35), textcoords='offset points', arrowprops=dict(arrowstyle="->", linewidth=2, connectionstyle="arc3, rad=.2"),) # Constructing indication arrows tax = 1.5
plt.savefig('Pflueger Model: cost of living in crowded area')             # Saves the model in C:\Users\

EXPLANATION COST OF LIVING

Introducing cluster effects

We also introduce positive effects from clusters. In a cluster, (skilled) labourers are able to produce more efficiently because they can profit from the proximity of other skilled labourers (Krugman, 1991). In our model, we assume that these positive effects take the form of $\gamma(\lambda-0.5)^2$, such that they become stronger when $\lambda$ takes up more extreme forms. In our model ,there is no effect for prices, as marginal costs are not based on the wage for skilled labor. That is, all the productivity gains made by skilled labour due to cluster effects only increase skilled labour wages. We assume, for simpliciity that this extra labour comes in the form of higher consumption of only manufactured goods.

In [144]:
# Defining extra parameter: clustere ffect
gamma = 0.8       # Cluster effect

# Constructing function including cluster effect
def utility_function_3(lamda):
    return (alpha/1-sigma)*np.log((lamda*phi+(1-lamda))/(lamda+(1-lamda)*phi)+gamma*(lamda-0.5)*(lamda-0.5))+((alpha*(1-phi))/sigma)*((rho+lamda)/(lamda+(1-lamda)*phi)-(rho+(1-lamda))/(lamda*phi+(1-lamda)))
In [145]:
# Itializing parameters tau and phi for tax = 1.1
tau = 1.1        # transport costs
phi = 0.621      # parameter for transport cost
# Estimate V-V* using tax = 1.1
my_second_range_v_v = utility_function_3(lamda) 

# Changing Parameter tau: 1.4
tau = 1.4        # transport costs
# Therefore phi becomes:
phi = 0.186      # parameter for transport cost
# Estimate V-V* using tax = 1.4
my_second_range_v_v_2 = utility_function_3(lamda) # Transportation cost 1.4

# Changing Parameter tau: 1.5
tau = 1.5        # transport costs
# Therefore phi becomes:
phi = 0.132      # parameter for transport cost
# Estimating V-V* using tax = 1.5
my_second_range_v_v_3 = utility_function_3(lamda) # Transportation cost 1.4

plt.clf() # Constructing a graph for tax = 1.1, 1.4, 1.5
plt.plot(lamda, my_second_range_v_v,'-', color = 'b', linewidth = 2)   # Constructs blue graphline for tax = 1.1
plt.plot(lamda, my_second_range_v_v_2,'-', color = 'r', linewidth = 2) # Constructs red graphline for tax = 1.4
plt.plot(lamda, my_second_range_v_v_3,'-', color = 'g', linewidth = 2) # Constructs green graphline for tax = 1.5
plt.title("Pflueger Model: cluster effect",fontsize = 15) # Titling of the graph
plt.xlabel("$\lambda$",fontsize = 15)      # Titling x-axis
plt.ylabel("$V-V^*$")                      # Titling y-axis
plt.annotate('$V-V^* (tax = 1.1)$', xy=(0.95,utility_function_3(0.57)), xycoords='data', xytext=(-90,-30), textcoords='offset points', arrowprops=dict(arrowstyle="->", linewidth=2, connectionstyle="arc3, rad=.2"),) # Constructing indication arrows tax = 1.1
plt.annotate('$V-V^* (tax = 1.4)$', xy=(0.90,utility_function_3(0.82)), xycoords='data', xytext=(-90,-40), textcoords='offset points', arrowprops=dict(arrowstyle="->", linewidth=2, connectionstyle="arc3, rad=.2"),) # Constructing indication arrows tax = 1.4
plt.annotate('$V-V^* (tax = 1.5)$', xy=(0.95,utility_function_3(0.92)), xycoords='data', xytext=(-70,18), textcoords='offset points', arrowprops=dict(arrowstyle="->", linewidth=2, connectionstyle="arc3, rad=.2"),) # Constructing indication arrows tax = 1.5
plt.savefig('Pfluger Model: cluster effect')             # Saves the model in C:\Users\

EXPLANATION WRONG MODELING EFFECTS MODEL

In [146]:
# Defining exogenous parameters

alpha = 0.3      # preference for manufactured goods
rho = 1          # ratio unskilled labour in home region to total skilled labour in world
tau = 1.4        # transport costs (tax = 1.4)
phi = 0.186      # parameter for transport cost (corresponding phi to tax of 1.4 = 0.186)
sigma = 0        # resetting sigma: elasticity of substitution between manufacturing varieties
lamda = arange (0.1,1.1,0.1) # Initialization lambda ranging from 0.1 to 1.0
In [147]:
# Same utility function as Pflüger (utility_function) can be used:
sigma = 5.0                                      # value for sigma assigned
my_third_range_v_v = utility_function(lamda)     # (tax = 1.4; sigma = 5.0)
sigma = 5.5                                      # value for sigma adjusted
my_third_range_v_v_2 = utility_function(lamda)   # (tax = 1.4; sigma = 5.5)
sigma = 6.0                                      # value for sigma adjusted
my_third_range_v_v_3 = utility_function(lamda)   # (tax = 1.4; sigma = 6.0)

plt.clf() # Constructing a graph for tax = 1.1, 1.4, 1.5
plt.plot(lamda, my_third_range_v_v,'-', color = 'b', linewidth = 2)   # Constructs blue graphline for tax = 1.1
plt.plot(lamda, my_third_range_v_v_2,'-', color = 'r', linewidth = 2) # Constructs red graphline for tax = 1.4
plt.plot(lamda, my_third_range_v_v_3,'-', color = 'g', linewidth = 2) # Constructs green graphline for tax = 1.5
plt.title("Pflueger Model: cluster effect",fontsize = 15) # Titling of the graph
plt.xlabel("$\lambda$",fontsize = 15)      # Titling x-axis
plt.ylabel("$V-V^*$")                      # Titling y-axis
plt.annotate('$V-V^* (tax 1.4; sigma 5.0)$', xy=(0.95,utility_function(0.88)), xycoords='data', xytext=(30,30), textcoords='offset points', arrowprops=dict(arrowstyle="->", linewidth=2, connectionstyle="arc3, rad=.2"),) # Constructing indication arrows sigma = 5.0
plt.annotate('$V-V^* (tax 1.4; sigma 5.5)$', xy=(0.95,utility_function(0.92)), xycoords='data', xytext=(30,30), textcoords='offset points', arrowprops=dict(arrowstyle="->", linewidth=2, connectionstyle="arc3, rad=.2"),) # Constructing indication arrows sigma 5.5
plt.annotate('$V-V^* (tax 1.4; sigma 6.0)$', xy=(0.95,utility_function(0.96)), xycoords='data', xytext=(30,30), textcoords='offset points', arrowprops=dict(arrowstyle="->", linewidth=2, connectionstyle="arc3, rad=.2"),) # Constructing indication arrows tax = 6.0
plt.savefig('Pfluger Model: adjusted sigma')             # Saves the model in C:\Users\

Findings

we fix for tax 1.4 and we let sigma vary 5, 5.5, 6

Conclusion

In [148]:
# Small additional video: interview with Paul Krugman
import io
import base64
from IPython.display import HTML

video = io.open('C:\Users\Arne Bor\Krugman.mp4', 'r+b').read()
encoded = base64.b64encode(video)

HTML(data='''<video alt="test" controls>
     <source src="data:video/mp4;base64,{0}" type="video/mp4" />
     </video>'''.format(encoded.decode('ascii')))
Out[148]:
In [ ]: